package com.youbug.mall.ware_wms.service.impl;

import com.youbug.common.exception.NoStockException;
import com.youbug.common.to.OrderTo;
import com.youbug.common.to.PmsSkuInfoTo;
import com.youbug.common.to.mq.StockDetailTo;
import com.youbug.common.to.mq.StockLockedTo;
import com.youbug.common.vo.R;
import com.youbug.mall.order_oms.vo.OrderItemVo;
import com.youbug.mall.order_oms.vo.WareSkuLockVo;
import com.youbug.mall.ware_wms.entity.WmsWareInfo;
import com.youbug.mall.ware_wms.entity.WmsWareOrderTask;
import com.youbug.mall.ware_wms.entity.WmsWareOrderTaskDetail;
import com.youbug.mall.ware_wms.entity.WmsWareSku;
import com.youbug.mall.ware_wms.feign.IWareOrderFeignService;
import com.youbug.mall.ware_wms.feign.IWmsPmsFeignService;
import com.youbug.mall.ware_wms.mapper.WmsWareSkuMapper;
import com.youbug.mall.ware_wms.service.IWmsWareInfoService;
import com.youbug.mall.ware_wms.service.IWmsWareOrderTaskDetailService;
import com.youbug.mall.ware_wms.service.IWmsWareOrderTaskService;
import com.youbug.mall.ware_wms.service.IWmsWareSkuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import com.youbug.common.vo.QueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品库存 服务实现类
 * </p>
 *
 * @author youbug
 * @since 2024-05-05
 */
@Service
public class WmsWareSkuServiceImpl extends ServiceImpl<WmsWareSkuMapper, WmsWareSku> implements IWmsWareSkuService {

        @Autowired
        private IWmsPmsFeignService pmsFeignService;
        @Autowired
        private IWmsWareInfoService wareInfoService;
        @Autowired
        private IWmsWareOrderTaskService wareOrderTaskService;
        @Autowired
        private IWmsWareOrderTaskDetailService wareOrderTaskDetailService;
        @Autowired
        private RabbitTemplate rabbitTemplate;
        @Autowired
        private IWareOrderFeignService orderFeignService;
        @Autowired
        private IWmsWareSkuService wareSkuService;

        @Override
        public IPage<WmsWareSku> getWmsWareSkuPage(QueryVo<WmsWareSku> queryVo) {

        Page<WmsWareSku> paramPage = new Page<>();

        paramPage.setCurrent(queryVo.getCurrentPage());

        paramPage.setSize(queryVo.getPageSize());

        QueryWrapper<WmsWareSku> wrapper = new QueryWrapper<>();

        WmsWareSku wmsWareSku = queryVo.getPayload();

        if(!ObjectUtils.isEmpty(wmsWareSku)){
            if(StringUtils.hasText(wmsWareSku.getSkuName())){
                wrapper.eq("sku_name", wmsWareSku.getSkuName());
            }
        }
        if(!ObjectUtils.isEmpty(queryVo.getStartTime())){
            wrapper.gt("create_time", queryVo.getStartTime());
        }
        if(!ObjectUtils.isEmpty(queryVo.getEndTime())){
            wrapper.lt("create_time", queryVo.getEndTime());
        }
        wrapper.orderByDesc("create_time");

        Page<WmsWareSku> page = this.page(paramPage, wrapper);
            List<WmsWareSku> records = page.getRecords();
            Set<Long> ids = records.stream().map(WmsWareSku::getWareId).collect(Collectors.toSet());

            if(!CollectionUtils.isEmpty(records)){
                List<WmsWareInfo> wareInfos = wareInfoService.list(new QueryWrapper<WmsWareInfo>().select("name", "id").in("id", ids));
                Map<Long, String> wareNameMap = wareInfos.stream().collect(Collectors.toMap(WmsWareInfo::getId, WmsWareInfo::getName, (v, v1) -> v));
                records.forEach(e->{
                    e.setWareName(wareNameMap.get(e.getWareId()));
                });
            }
            return page;
        }

       /* @Transactional(transactionManager = "transactionManagerXXX", rollbackFor = Exception.class)
        public boolean saveBatch(Collection<WmsWareSku> entityList) {
        return saveBatch(entityList, DEFAULT_BATCH_SIZE);
        }
        */
    @Override
    public void unlockStock(StockLockedTo to) {
        StockDetailTo detail = to.getDetail();
        WmsWareOrderTaskDetail orderTaskDetail = wareOrderTaskDetailService.getById(detail.getId());

        if(orderTaskDetail != null){ // 库存锁定成功，判断订单
            // 解锁
            WmsWareOrderTask orderTask = wareOrderTaskService.getById(to.getId());
            if(orderTask!=null){
                String orderSn = orderTask.getOrderSn();
                R<OrderTo> r = orderFeignService.getOrderBySn(orderSn);

                if(r.getCode() == R.SUCCESS){
                    OrderTo order = r.getData();

                    if(order==null || order.getStatus() == 4){// 订单取消，解锁
                        unLockStock(orderTaskDetail.getSkuId(), orderTaskDetail.getWareId(),
                                orderTaskDetail.getSkuNum(), orderTaskDetail.getId());
                    }
                }
            }
            // 无订单 无需解锁
            // 有订单，判断状态，已取消，解锁，没取消，不能解锁
        }
    }

    @Override // 防止订单服务卡顿，导致订单状态消息改不了，库存消息有限到期，查订单状态为新建状态，什么都不做就走了
    public void unlockStock(OrderTo orderTo) {
        String orderSn = orderTo.getOrderSn();
        // 查一下最新库存状态，防止重复解锁库存
        WmsWareOrderTask task = wareOrderTaskService.getOrderTaskByOrderSn(orderSn);

        Long id = task.getId();
        // 按照工作单id，找到所有没有解锁的库存，进行解锁
        List<WmsWareOrderTaskDetail> taskDetailList = wareOrderTaskDetailService.list(new QueryWrapper<WmsWareOrderTaskDetail>()
                .eq("task_id", id)
                .eq("lock_status", 1));

        for (WmsWareOrderTaskDetail detail : taskDetailList) {
            unLockStock(detail.getSkuId(), detail.getWareId(), detail.getSkuNum(), detail.getId());
        }
    }

    private void unLockStock(Long skuId, Long wareId, Integer skuNum, Long detailId) {

        WmsWareSku wareSku = wareSkuService.getOne(new QueryWrapper<WmsWareSku>().eq("sku_id", skuId).eq("ware_id", wareId));
        wareSku.setStockLocked(wareSku.getStockLocked() - skuNum);
        boolean update = wareSkuService.update(wareSku, new QueryWrapper<WmsWareSku>());
    }

    @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {
        WmsWareSku one = this.getOne(new QueryWrapper<WmsWareSku>().eq("sku_id", skuId)
                .eq("ware_id",wareId));
        if(one!=null){
            one.setStock(one.getStock()+skuNum);
            this.updateById(one);
        }else{
            WmsWareSku wareSku = new WmsWareSku();
            wareSku.setSkuId(skuId);
            PmsSkuInfoTo info = pmsFeignService.getSkuInfoById(skuId);
            wareSku.setSkuName(info.getSkuName());
            wareSku.setStock(skuNum);
            wareSku.setWareId(wareId);

            this.save(wareSku);
        }
    }

    @Override
    @Transactional(transactionManager = "transactionManagerWms", rollbackFor = Exception.class)
    public R<Boolean> orderLockStock(WareSkuLockVo lockVo) {

        WmsWareOrderTask wareOrderTask = new WmsWareOrderTask();
        wareOrderTask.setOrderSn(lockVo.getOrderSn());
        wareOrderTaskService.save(wareOrderTask);

        List<OrderItemVo> locks = lockVo.getLocks();

        List<SkuWareHasStock> collect = locks.stream().map((item) -> {
            SkuWareHasStock stock = new SkuWareHasStock();
            Long skuId = item.getSkuId();
            stock.setSkuId(skuId);
            stock.setNum(item.getCount());
            //查询这个商品在哪个仓库有库存
            List<WmsWareSku> wareSkus = this.list(new QueryWrapper<WmsWareSku>()
                    .eq("sku_id", skuId).ge("stock",item.getCount()));// 商品有足够库存的仓库
            if(!CollectionUtils.isEmpty(wareSkus)){
                stock.setWares(wareSkus);
            }
            return stock;
        }).collect(Collectors.toList());

        for (SkuWareHasStock wareHasStock: collect) {

            boolean skuStocked = false;
            Long skuId = wareHasStock.getSkuId();
            if (CollectionUtils.isEmpty(wareHasStock.getWares())) {
                //没有任何仓库有这个商品的库存
                throw new NoStockException(skuId);
            }
            List<WmsWareSku> wares = wareHasStock.getWares();

            for (WmsWareSku wareSku : wares) {

                wareSku.setStockLocked(wareSku.getStockLocked() + wareHasStock.getNum());
                // 锁定库存
                boolean update = this.updateById(wareSku);
                if(update){
                    skuStocked = true;
                    WmsWareOrderTaskDetail orderTaskDetail = new WmsWareOrderTaskDetail(null, wareSku.getSkuId(), wareSku.getSkuName(), wareHasStock.getNum(),
                            wareOrderTask.getId(), wareSku.getWareId(),1);
                    wareOrderTaskDetailService.save(orderTaskDetail);

                    StockLockedTo stockLockedTo = new StockLockedTo();

                    stockLockedTo.setId(wareOrderTask.getId());

                    StockDetailTo detail = new StockDetailTo();

                    BeanUtils.copyProperties(orderTaskDetail, detail);

                    stockLockedTo.setDetail(detail);

                    rabbitTemplate.convertAndSend("stock-event-exchange","stock.locked", stockLockedTo);
                    break;
                }
            }
            if (!skuStocked) {
                //当前商品所有仓库都没有锁住
                throw new NoStockException(skuId);
            }
        }
        return R.ok();
    }


    @Data
    private class SkuWareHasStock {
        private Long skuId;
        private Integer num;
        private List<WmsWareSku> wares;
    }
}
